www.gusucode.com > VC++ 信息加密聊天源代码-源码程序 > VC++ 信息加密聊天源代码-源码程序\code\SecChat\SecretKeyEdit.cpp

    //Download by http://www.NewXing.com
// SecretKeyEdit.cpp : implementation file
//

#include "stdafx.h"
#include "secretchat.h"
#include "SecretKeyEdit.h"
#include "RSA.h"
#include "SecretChatDlg.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CSecretKeyEdit dialog


CSecretKeyEdit::CSecretKeyEdit(CWnd* pParent /*=NULL*/)
	: CDialog(CSecretKeyEdit::IDD, pParent)
{
	//{{AFX_DATA_INIT(CSecretKeyEdit)
	m_email = _T("");
	m_qq = _T("");
	m_userName = _T("");
	m_secretKeyEdit = _T("");
	//}}AFX_DATA_INIT
}


void CSecretKeyEdit::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CSecretKeyEdit)
	DDX_Text(pDX, IDC_EMAIL, m_email);
	DDV_MaxChars(pDX, m_email, 32);
	DDX_Text(pDX, IDC_QQ, m_qq);
	DDV_MaxChars(pDX, m_qq, 32);
	DDX_Text(pDX, IDC_USERNAME, m_userName);
	DDV_MaxChars(pDX, m_userName, 32);
	DDX_Text(pDX, IDC_SECRETKEY, m_secretKeyEdit);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CSecretKeyEdit, CDialog)
	//{{AFX_MSG_MAP(CSecretKeyEdit)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSecretKeyEdit message handlers
DWORD WINAPI create_secret_key_thread(LPVOID param)	//创建密钥线程函数
{
	CSecretKeyEdit * pKey = (CSecretKeyEdit *)param;

	//查看文件是否存在
	CFileFind find;
	if( find.FindFile(pKey->m_user_private_key_file_name) )
	{
		//提示文件存在并退出
		MessageBox(
			NULL,
			"文件已经存在",
			"生成私钥文件",
			MB_ICONEXCLAMATION);
		pKey->SetWindowText("创建新的用户密钥");
		pKey->m_bCreate = TRUE;	//能再创建
		return 0;
	}

	//生成密钥和用户信息
	private_key key;
	key.create();
	key.vlong_to_SK(pKey->m_secretKey.sk);
	key.vlong_to_PK(pKey->m_secretKey.pk);
	pKey->CStringToChar(
		pKey->m_secretKey.userName,
		pKey->m_userName,
		32);
	pKey->CStringToChar(
		pKey->m_secretKey.qq,
		pKey->m_qq,
		32);
	pKey->CStringToChar(
		pKey->m_secretKey.email,
		pKey->m_email,
		32);
	pKey->m_secretKey.version = SECRETKEY_VERSION;
	pKey->m_secretKey.privateOrPublic = SECRETKEY_PRIVATE;
	pKey->m_secretKey.ID = SECRETKEY_ID;


	//把密钥信息写入文件,私钥文件
	CFile file;
	file.Open(
		pKey->m_user_private_key_file_name,
		CFile::modeCreate | CFile::modeReadWrite | CFile::typeBinary);
	file.Write(
		&pKey->m_secretKey,
		sizeof(SecretKey));	//写入信息
	file.Close();

	//把密钥信息写入文件,公钥文件
	pKey->CreatePublicKey(pKey->m_user_private_key_file_name);

	//提示成功
	MessageBox(
		NULL,
		"已经生成密钥,可以安全的进行通讯。",
		"密聊",
		MB_ICONINFORMATION);
	//更新列表,如果没m_publicKeyManagerDlg窗口就会出错
	//pSecretChatDlg->m_setupDlg.ShowTabWindow(1);

	pKey->m_bCreate = TRUE;	//可以再创建
	pKey->SetWindowText("创建新的用户密钥");

	return 0;
}

void CSecretKeyEdit::OnOK() 
{
	if(!m_bCreate)
	{
		MessageBox(
			"创建密钥中",
			"密聊",
			MB_ICONINFORMATION);
		return;
	}

	CSecretChatDlg * pSecretChatDlg = (CSecretChatDlg *)AfxGetMainWnd();

	if(!UpdateData()) return;

	CEdit *pTemp;
	if(m_userName == "")
	{ 
		pTemp = (CEdit *)GetDlgItem(IDC_USERNAME);
		pTemp->SetFocus();
		//不能为空
		MessageBox(
			"不能为空",
			"warning",
			MB_ICONEXCLAMATION);
		return;
	}
	else if(m_qq == "")
	{ 
		pTemp = (CEdit *)GetDlgItem(IDC_QQ);
		pTemp->SetFocus();
		//不能为空
		MessageBox(
			"不能为空",
			"warning",
			MB_ICONEXCLAMATION);
		return;
	}
	else if(m_email == "")
	{ 
		pTemp = (CEdit *)GetDlgItem(IDC_EMAIL);
		pTemp->SetFocus();
		//不能为空
		MessageBox(
			"不能为空",
			"warning",
			MB_ICONEXCLAMATION);
		return;
	}

	if(m_select == SELECT_CREATE)
	{	
		SetWindowText("创建新的用户密钥 (正在创建中)");
		m_user_private_key_file_name = 
			pSecretChatDlg->m_appName + "\\user\\" + m_userName + ".sk";

		m_bCreate = FALSE;	//不能再创建
		unsigned long nThreadID;
		::CreateThread(
			NULL,
			0,
			create_secret_key_thread,
			this,
			0,
			&nThreadID);
		return;

	}
	else //SELECT_PRIVATE和SELECT_PUBLIC的处理相同
	{	
		CStringToChar(
			m_secretKey.qq,
			m_qq,
			32);
		CStringToChar(
			m_secretKey.email,
			m_email,
			32);
		//更改密钥信息写入私钥文件
		CFile file;
		file.Open(
			m_fileName,//密钥的文件全路径
			CFile::modeReadWrite | CFile::typeBinary);
		file.SeekToBegin();
		file.Write(
			&m_secretKey,
			sizeof(SecretKey));	//写入信息
		file.Close();
	}
	
	CDialog::OnOK();
}

void CSecretKeyEdit::OnCancel() 
{
	if(!m_bCreate)
	{
		MessageBox(
			"创建密钥中",
			"密聊",
			MB_ICONINFORMATION);
		return;
	}
	
	CDialog::OnCancel();
}

BOOL CSecretKeyEdit::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	CEdit *pUserName = (CEdit *)GetDlgItem(IDC_USERNAME);
	CStatic *pSecretKeyStatic = (CStatic *)GetDlgItem(IDC_SECRETKEYSTATIC);
	CButton *pOK = (CButton *)GetDlgItem(IDOK);
	CEdit *psecretKey = (CEdit *)GetDlgItem(IDC_SECRETKEY);
	if(m_select == SELECT_CREATE)
	{
		pSecretKeyStatic->SetWindowText("生成密钥说明:");
		pUserName->SetReadOnly(FALSE);
		SetWindowText("创建新的用户密钥");
		pOK->SetWindowText("生成");
		
		CString str;
		str.LoadString(IDS_CREATEPUBLICKEYHELP);
		psecretKey->SetWindowText(str);
		//psecretKey->SetWindowText("    \"密聊\"采用 2048bit 的 RSA 数据加密算法对数据进行加密和数字签名,在使用前必须生成用户的私钥和公钥。\r\n    只要通过安全通道相互把公钥传递给通讯方后,彼此就可以进行安全的通话和身份验证了。\r\n    生成私有密钥文件 [用户名.sk] 和公开密钥文件 [用户名.pk] 的过程需要稍等几分钟...");
	}
	else if(m_select == SELECT_PRIVATE)
	{
		pSecretKeyStatic->SetWindowText("私钥信息(2048bit):");
		pUserName->SetReadOnly();
		SetWindowText("用户私钥编辑");
		pOK->SetWindowText("更改");
	}
	else if(m_select == SELECT_PUBLIC)
	{
		pSecretKeyStatic->SetWindowText("公钥信息(2048bit):");
		pUserName->SetReadOnly();
		SetWindowText("好友公钥编辑");
		pOK->SetWindowText("更改");
	}

	m_bCreate = TRUE;	//可以再创建

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

CString CSecretKeyEdit::CharToHexToString(char m)	//把一个字符转换成十六进制再用字符表示
{
	char hex;
	CString strHex;
	//左边4位的表示
	hex = m & (char)0xf0;
	hex = hex >> 4;
	hex = hex & (char)0xf;	//有时被移进来的为会为1
	switch(hex)
	{
	case 0:
		strHex = "0";
		break;
	case 1:
		strHex = "1";
		break;
	case 2:
		strHex = "2";
		break;
	case 3:
		strHex = "3";
		break;
	case 4:
		strHex = "4";
		break;
	case 5:
		strHex = "5";
		break;
	case 6:
		strHex = "6";
		break;
	case 7:
		strHex = "7";
		break;
	case 8:
		strHex = "8";
		break;
	case 9:
		strHex = "9";
		break;
	case 10:
		strHex = "A";
		break;
	case 11:
		strHex = "B";
		break;
	case 12:
		strHex = "C";
		break;
	case 13:
		strHex = "D";
		break;
	case 14:
		strHex = "E";
		break;
	case 15:
		strHex = "F";
		break;
	}

	//右边4位的表示
	hex = m & (char)0xf;
	switch(hex)
	{
	case 0:
		strHex += "0";
		break;
	case 1:
		strHex += "1";
		break;
	case 2:
		strHex += "2";
		break;
	case 3:
		strHex += "3";
		break;
	case 4:
		strHex += "4";
		break;
	case 5:
		strHex += "5";
		break;
	case 6:
		strHex += "6";
		break;
	case 7:
		strHex += "7";
		break;
	case 8:
		strHex += "8";
		break;
	case 9:
		strHex += "9";
		break;
	case 10:
		strHex += "A";
		break;
	case 11:
		strHex += "B";
		break;
	case 12:
		strHex += "C";
		break;
	case 13:
		strHex += "D";
		break;
	case 14:
		strHex += "E";
		break;
	case 15:
		strHex += "F";
		break;
	}

	return strHex;
}

int CSecretKeyEdit::validateSecretKey(CString fileName)	
{ //验证是不是密钥文件(私钥为1,公钥为2,都不是为0)
	m_fileName = fileName;
	CFile file;
	if(!file.Open(
		fileName,
		CFile::modeReadWrite | CFile::typeBinary))
		return 0;
	if(file.GetLength() != sizeof(SecretKey))
		return 0;
	file.SeekToBegin();
	file.Read(&m_secretKey, sizeof(SecretKey));
	file.Close();

	if(m_secretKey.ID != SECRETKEY_ID)
		return 0;

	m_userName = CharToCString(m_secretKey.userName, 32);
	m_qq = CharToCString(m_secretKey.qq, 32);
	m_email = CharToCString(m_secretKey.email, 32);

	char chTemp[2048 / 8];
	if(m_secretKey.privateOrPublic == SECRETKEY_PRIVATE)
	{		
		::MoveMemory(
			chTemp,						//目标
			(char *)&m_secretKey.sk,	//源内容
			2048 / 8);
	}
	else
	{	
		::MoveMemory(
			chTemp,						//目标
			(char *)&m_secretKey.pk,	//源内容
			2048 / 8);
	}
	
	//将密钥换成二进制显示
	m_secretKeyEdit = "";
	for(int i = 0;i < 256;i++)
	{
		m_secretKeyEdit += CharToHexToString(chTemp[i]) + " ";
		if(!(i == 0 || i == 255))
		{
			if((i + 1) % 16 == 0)
				m_secretKeyEdit += "\r\n";
		}
	}

	return m_secretKey.privateOrPublic;
}

void CSecretKeyEdit::CStringToChar(char *ch, CString str,int n)
{	//字符串转到字符数组
	for( int i = 0;i < str.GetLength();i++)
	{
		if( i == n) return;
		ch[i] = str[i];
	}
	if( i == n) return;	//为了使数组char[n]不越界,才要这样做的
	ch[i] = NULL;
}

CString CSecretKeyEdit::CharToCString(char *ch, int n/*char数组的大小*/)
{	////字符数组转到字符串
	CString str;
	char * pbuf = new char[n + 1];
	pbuf[n] = NULL;

	for( int i = 0;i <  n;i++)
		pbuf[i] = ch[i];
	str = pbuf;
	delete[] pbuf;
	return str;
}


BOOL CSecretKeyEdit::CreatePublicKey(CString fileName)	//生成公钥
{
	SecretKey secretKey;

	CFile file;
	if(!file.Open(
		fileName,
		CFile::modeReadWrite | CFile::typeBinary))
		return FALSE;
	if(file.GetLength() != sizeof(SecretKey))
		return FALSE;
	file.SeekToBegin();
	file.Read(&secretKey, sizeof(SecretKey));
	file.Close();

	//私钥文件名要转换成对应的公钥文件名
	fileName.SetAt(
		fileName.GetLength() - 2,
		'p');

	//把密钥信息写入文件,公钥文件
	char chTemp[2048 / 8];
	for(int i = 0;i < (2048 / 8);i++)
	{
		chTemp[i] = 0;
	}
	::MoveMemory(
		(char *)&secretKey.sk,	//目标
		chTemp,	//源内容
		2048 / 8);
	secretKey.privateOrPublic = SECRETKEY_PUBLIC;

	//查看文件是否存在
	WIN32_FIND_DATA wfd;
	HANDLE hSearch = ::FindFirstFile(
		fileName,//密钥的文件全路径
		&wfd);
	if( hSearch != INVALID_HANDLE_VALUE) //文件存在
	{
		//提示文件存在并退出
		if(MessageBox(
			"文件已经存在。覆盖 " + fileName + " 文件吗?",
			"生成公钥文件",
			MB_YESNO | MB_ICONQUESTION) == IDNO)
		{
			return FALSE;
		}

	}
	file.Open(
		fileName,//密钥的文件全路径
		CFile::modeCreate | CFile::modeReadWrite | CFile::typeBinary);
	file.Write(
		&secretKey,
		sizeof(SecretKey));	//写入信息
	file.Close();

	return TRUE;
}